"""
GitCode MCP服务器，提供GitCode API功能的MCP接口
"""
import json
import logging
import os
import sys
from typing import Optional

from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP

from gitcode_mcp.api.base.client import GitCodeAPI

# 配置日志
# 注意：MCP服务器使用stdio通信，stdout只能用于JSON-RPC消息
# 日志必须输出到stderr或文件，否则会导致协议解析错误
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(sys.stderr),  # 输出到标准错误流
        logging.FileHandler("gitcode_mcp.log")
    ]
)
logger = logging.getLogger("gitcode_mcp")
logger.info("GitCode MCP服务器模块初始化...")

# 加载环境变量
load_dotenv()
logger.info("环境变量已加载")

# 创建FastMCP服务器实例
mcp = FastMCP("GitCode MCP服务器")
logger.info(f"FastMCP实例已创建，名称: GitCode MCP服务器")
api_client: Optional[GitCodeAPI] = None


# 初始化API客户端
def init_api_client():
    """初始化API客户端"""
    global api_client
    if api_client is not None:
        return api_client
        
    token = os.environ.get("GITCODE_TOKEN")
    if not token:
        logger.warning("未设置GITCODE_TOKEN环境变量，API访问可能受限")
    
    # 从环境变量读取代理配置
    proxy = os.environ.get("HTTP_PROXY") or os.environ.get("HTTPS_PROXY")
    if proxy:
        logger.info(f"检测到代理配置: {proxy}")
    
    api_client = GitCodeAPI(token=token, proxy=proxy)
    logger.info("GitCode API客户端已初始化")
    return api_client


# 辅助函数
async def safe_api_call(func, *args, **kwargs):
    """安全调用API，统一处理错误和日志"""
    client = init_api_client()
    
    try:
        return await func(*args, **kwargs)
    except Exception as e:
        error_message = f"API调用失败: {func.__name__}({args}, {kwargs}) - {str(e)}"
        logger.error(error_message)
        raise ValueError(error_message) from e


# === 工具 ===

@mcp.tool()
async def list_repositories() -> str:
    """列出当前用户的仓库"""
    client = init_api_client()
    repos = await safe_api_call(client.repos.list_user_repos)
    return json.dumps(repos, ensure_ascii=False)


@mcp.tool()
async def get_repository(owner: str, repo: str) -> str:
    """获取特定仓库的详细信息"""
    client = init_api_client()
    repo_info = await safe_api_call(client.repos.get_repo, owner=owner, repo=repo)
    return json.dumps(repo_info, ensure_ascii=False)


@mcp.tool()
async def create_repository(name: str, description: str = "", private: bool = False) -> str:
    """创建新仓库"""
    client = init_api_client()
    repo = await safe_api_call(client.repos.create_repo, name=name, description=description, private=private)
    return json.dumps(repo, ensure_ascii=False)


@mcp.tool()
async def list_branches(owner: str, repo: str) -> str:
    """列出仓库的分支"""
    client = init_api_client()
    branches = await safe_api_call(client.branches.list_branches, owner=owner, repo=repo)
    return json.dumps(branches, ensure_ascii=False)


@mcp.tool()
async def get_branch(owner: str, repo: str, branch: str) -> str:
    """获取特定分支的详细信息"""
    client = init_api_client()
    branch_info = await safe_api_call(client.branches.get_branch, owner=owner, repo=repo, branch=branch)
    return json.dumps(branch_info, ensure_ascii=False)


@mcp.tool()
async def create_branch(owner: str, repo: str, branch: str, ref: str) -> str:
    """创建新分支"""
    client = init_api_client()
    branch_info = await safe_api_call(client.branches.create_branch, owner=owner, repo=repo, branch=branch, ref=ref)
    return json.dumps(branch_info, ensure_ascii=False)


@mcp.tool()
async def list_issues(owner: str, repo: str) -> str:
    """列出仓库的Issues"""
    client = init_api_client()
    issues = await safe_api_call(client.issues.list_issues, owner=owner, repo=repo)
    return json.dumps(issues, ensure_ascii=False)


@mcp.tool()
async def get_issue(owner: str, repo: str, issue_number: int) -> str:
    """获取特定Issue的详细信息"""
    client = init_api_client()
    issue = await safe_api_call(client.issues.get_issue, owner=owner, repo=repo, issue_number=issue_number)
    return json.dumps(issue, ensure_ascii=False)


@mcp.tool()
async def create_issue(owner: str, repo: str, title: str, body: str = "") -> str:
    """创建新Issue"""
    client = init_api_client()
    issue = await safe_api_call(client.issues.create_issue, owner=owner, repo=repo, title=title, body=body)
    return json.dumps(issue, ensure_ascii=False)


@mcp.tool()
async def list_issue_comments(owner: str, repo: str, issue_number: int) -> str:
    """列出Issue的评论列表"""
    client = init_api_client()
    comments = await safe_api_call(
        client.issues.list_comments,
        owner=owner,
        repo=repo,
        issue_number=issue_number
    )
    return json.dumps(comments, ensure_ascii=False)


@mcp.tool()
async def create_issue_comment(owner: str, repo: str, issue_number: int, body: str) -> str:
    """创建Issue评论"""
    client = init_api_client()
    comment = await safe_api_call(
        client.issues.add_comment,
        owner=owner,
        repo=repo,
        issue_number=issue_number,
        body=body
    )
    return json.dumps(comment, ensure_ascii=False)


@mcp.tool()
async def list_pull_requests(owner: str, repo: str) -> str:
    """列出仓库的Pull Requests"""
    client = init_api_client()
    prs = await safe_api_call(client.pulls.list_pull_requests, owner=owner, repo=repo)
    return json.dumps(prs, ensure_ascii=False)


@mcp.tool()
async def get_pull_request(owner: str, repo: str, pull_number: int) -> str:
    """获取特定Pull Request的详细信息"""
    client = init_api_client()
    pr = await safe_api_call(client.pulls.get_pull_request, owner=owner, repo=repo, pr_number=pull_number)
    return json.dumps(pr, ensure_ascii=False)


@mcp.tool()
async def create_pull_request(owner: str, repo: str, title: str, head: str, base: str, body: str = "") -> str:
    """创建新Pull Request"""
    client = init_api_client()
    pr = await safe_api_call(
        client.pulls.create_pull_request, 
        owner=owner, 
        repo=repo, 
        title=title, 
        head=head, 
        base=base, 
        body=body
    )
    return json.dumps(pr, ensure_ascii=False)


@mcp.tool()
async def update_pull_request(owner: str, repo: str, pull_number: int, title: str = None, body: str = None, state: str = None) -> str:
    """更新Pull Request"""
    client = init_api_client()
    pr = await safe_api_call(
        client.pulls.update_pull_request,
        owner=owner,
        repo=repo,
        pr_number=pull_number,
        title=title,
        body=body,
        state=state
    )
    return json.dumps(pr, ensure_ascii=False)


@mcp.tool()
async def merge_pull_request(owner: str, repo: str, pull_number: int, commit_title: str = None, commit_message: str = None, merge_method: str = None) -> str:
    """合并Pull Request"""
    client = init_api_client()
    result = await safe_api_call(
        client.pulls.merge_pull_request,
        owner=owner,
        repo=repo,
        pr_number=pull_number,
        commit_title=commit_title,
        commit_message=commit_message,
        merge_method=merge_method
    )
    return json.dumps(result, ensure_ascii=False)


@mcp.tool()
async def list_pull_request_comments(owner: str, repo: str, pull_number: int) -> str:
    """列出Pull Request的评论列表"""
    client = init_api_client()
    comments = await safe_api_call(
        client.pulls.list_pull_request_comments,
        owner=owner,
        repo=repo,
        pr_number=pull_number
    )
    return json.dumps(comments, ensure_ascii=False)


@mcp.tool()
async def create_pull_request_comment(owner: str, repo: str, pull_number: int, body: str, path: str = None, position: int = None) -> str:
    """在Pull Request添加评论（可选path和position用于代码行评论）"""
    client = init_api_client()
    comment = await safe_api_call(
        client.pulls.create_pull_request_comment,
        owner=owner,
        repo=repo,
        pr_number=pull_number,
        body=body,
        path=path,
        position=position
    )
    return json.dumps(comment, ensure_ascii=False)


# === 搜索功能 ===
# 注意：以下搜索功能暂时注释，因为平台目前不支持

# @mcp.tool()
# async def search_code(query: str) -> str:
#     """搜索代码"""
#     client = init_api_client()
#     results = await safe_api_call(client.search.search_code, query=query)
#     return json.dumps(results, ensure_ascii=False)

@mcp.tool()
async def search_repositories(query: str) -> str:
    """搜索仓库"""
    client = init_api_client()
    results = await safe_api_call(client.search.search_repositories, query=query)
    return json.dumps(results, ensure_ascii=False)


@mcp.tool()
async def search_issues(query: str) -> str:
    """搜索Issues"""
    client = init_api_client()
    results = await safe_api_call(client.search.search_issues, query=query)
    return json.dumps(results, ensure_ascii=False)


@mcp.tool()
async def search_users(query: str) -> str:
    """搜索用户"""
    client = init_api_client()
    results = await safe_api_call(client.search.search_users, query=query)
    return json.dumps(results, ensure_ascii=False)


# === 资源 ===

@mcp.resource("repo://{owner}/{name}")
async def get_repository_resource(owner: str, name: str) -> str:
    """获取仓库资源"""
    client = init_api_client()
    
    try:
        repo_data = await safe_api_call(client.repos.get_repo, owner=owner, repo=name)
        formatted_content = (
            f"# {repo_data.get('name')}\n\n"
            f"{repo_data.get('description', '')}\n\n"
            f"- 所有者: {owner}\n"
            f"- 星标数: {repo_data.get('stargazers_count', 0)}\n"
            f"- Fork数: {repo_data.get('forks_count', 0)}\n"
            f"- 默认分支: {repo_data.get('default_branch', 'main')}\n"
            f"- 创建时间: {repo_data.get('created_at', '')}\n"
            f"- 最后更新: {repo_data.get('updated_at', '')}\n"
        )
        
        return formatted_content
    except Exception as e:
        logger.error(f"读取资源时出错: {owner}/{name} - {e}")
        return f"Error: {str(e)}"


# === 提示模板 ===

@mcp.prompt()
def create_issue_prompt(owner: str, repo: str, title: str, body: str = "") -> str:
    """创建Issue的提示模板"""
    return f"""在 {owner}/{repo} 仓库中创建一个新Issue：

标题：{title}

内容：{body}"""


@mcp.prompt()
def create_pull_request_prompt(owner: str, repo: str, title: str, head: str, base: str, body: str = "") -> str:
    """创建Pull Request的提示模板"""
    return f"""在 {owner}/{repo} 仓库中创建一个新Pull Request：

标题：{title}

从分支 {head} 到 {base}

描述：{body}"""


# @mcp.prompt()
# def search_code_prompt(query: str) -> str:
#     """搜索代码的提示模板"""
#     return f"""搜索代码片段：{query}"""


def main():
    """主函数，启动MCP服务器"""
    logger.info("正在启动GitCode MCP服务器...")
    try:
        # 初始化API客户端
        init_api_client()
        logger.info("API客户端已初始化，准备启动服务器...")
        
        # FastMCP.run() 会启动服务器并保持运行
        mcp.run()
    except KeyboardInterrupt:
        logger.info("服务器被用户中断")
    except Exception as e:
        logger.error(f"服务器运行错误: {e}", exc_info=True)
        raise
    finally:
        # 清理资源
        import asyncio
        if api_client:
            try:
                asyncio.run(api_client.close())
                logger.info("API客户端已关闭")
            except Exception as e:
                logger.error(f"关闭API客户端时出错: {e}")


if __name__ == "__main__":
    main()
